// 26_advanced_traits_generics.rs
// Rust内卷终极指南：5个让同事"高攀不起"的Trait与泛型骚操作

fn main() {
    println!("=== Rust内卷终极指南：5个让同事\"高攀不起\"的Trait与泛型骚操作 ===\n");
    
    // 天坑一：屠龙刀用来切菜 —— 不必要的泛型滥用
    println!("天坑一：屠龙刀用来切菜 —— 不必要的泛型滥用");
    demo_unnecessary_generics();
    
    // 天坑二：代码界的"意面"—— 杂乱无章的Trait约束
    println!("\n天坑二：代码界的\"意面\"—— 杂乱无章的Trait约束");
    demo_where_clauses();
    
    // 天坑三：错把"静态"当"动态"—— 混淆泛型与Trait对象
    println!("\n天坑三：错把\"静态\"当\"动态\"—— 混淆泛型与Trait对象");
    demo_static_vs_dynamic();
    
    // 天坑四：给Trait"家族"添乱——不用关联类型，自找麻烦
    println!("\n天坑四：给Trait\"家族\"添乱——不用关联类型，自找麻烦");
    demo_associated_types();
    
    // 天坑五：过早的"承诺"——在结构体上滥用约束
    println!("\n天坑五：过早的\"承诺\"——在结构体上滥用约束");
    demo_struct_constraints();
    
    println!("\n关注梦兽编程微信公众号，幽默学习Rust");
}

// 天坑一：屠龙刀用来切菜 —— 不必要的泛型滥用
fn demo_unnecessary_generics() {
    println!("1. 不必要的泛型滥用示例：");
    
    // 不明智的做法 - 不必要的泛型
    fn print_value_unnecessary<T: std::fmt::Debug>(value: T) {
        println!("不必要的泛型: {:?}", value);
    }
    
    // 更明智的做法 - 具体类型
    fn print_value_specific(value: i32) {
        println!("具体类型: {:?}", value);
    }
    
    // 测试两种方法
    print_value_unnecessary(42);
    print_value_specific(42);
    
    println!("建议：只有当你真正需要处理多种类型时，再去召唤泛型这条\"神龙\"");
}

// 天坑二：代码界的"意面"—— 杂乱无章的Trait约束
fn demo_where_clauses() {
    println!("2. 使用where子句优化Trait约束：");
    
    // 不明智的做法 - 混乱的尖括号约束
    fn log_json_bad<T: std::fmt::Debug + Clone>(item: T) {
        println!("混乱的约束: {:?}", item);
    }
    
    // 更明智的做法 - 使用where子句
    fn log_json_good<T>(item: T)
    where
        T: std::fmt::Debug + Clone,
    {
        println!("清晰的约束: {:?}", item);
    }
    
    // 多参数示例
    fn process_data<T, U>(a: T, b: U)
    where
        T: Clone + std::fmt::Debug,
        U: Default + std::fmt::Debug,
    {
        println!("处理数据A: {:?}, 数据B: {:?}", a, b);
    }
    
    // 测试
    let data = "Hello Rust";
    log_json_bad(data.to_string());
    log_json_good(data.to_string());
    process_data(42, "World");
    
    println!("建议：把约束条件从尖括号里解放出来，交给where子句去管理");
}

// 天坑三：错把"静态"当"动态"—— 混淆泛型与Trait对象
fn demo_static_vs_dynamic() {
    println!("3. 静态分发 vs 动态分发：");
    
    // 定义Drawable trait
    trait Drawable {
        fn draw(&self);
    }
    
    #[derive(Debug)]
    struct Circle {
        radius: f64,
    }
    
    #[derive(Debug)]
    struct Square {
        side: f64,
    }
    
    impl Drawable for Circle {
        fn draw(&self) {
            println!("绘制圆形，半径: {}", self.radius);
        }
    }
    
    impl Drawable for Square {
        fn draw(&self) {
            println!("绘制正方形，边长: {}", self.side);
        }
    }
    
    // 静态分发 - 泛型版本（一次只能接受一种具体类型）
    fn draw_static<T: Drawable>(item: T) {
        item.draw();
    }
    
    // 动态分发 - Trait对象版本（可以接受任何实现了Drawable的类型）
    fn draw_dynamic(item: &dyn Drawable) {
        item.draw();
    }
    
    // 使用枚举进行动态分发 - 另一种动态分发方式
    #[derive(Debug)]
    enum Shape {
        Circle(Circle),
        Square(Square),
    }
    
    impl Shape {
        fn draw(&self) {
            match self {
                Shape::Circle(circle) => circle.draw(),
                Shape::Square(square) => square.draw(),
            }
        }
    }
    
    // 渲染场景 - 使用Trait对象处理异构集合
    fn render_scene(items: Vec<Box<dyn Drawable>>) {
        println!("渲染场景:");
        for item in items {
            item.draw();
        }
    }
    
    // 渲染场景 - 使用枚举处理异构集合
    fn render_scene_with_enum(shapes: Vec<Shape>) {
        println!("使用枚举渲染场景:");
        for shape in shapes {
            shape.draw();
            // 可以访问枚举的具体类型信息
            println!("  形状详情: {:?}", shape);
        }
    }
    
    // 测试
    let circle = Circle { radius: 5.0 };
    let square = Square { side: 3.0 };
    
    println!("静态分发:");
    draw_static(circle);
    
    println!("动态分发:");
    draw_dynamic(&square);
    
    println!("使用枚举进行动态分发:");
    let shape_circle = Shape::Circle(Circle { radius: 6.0 });
    let shape_square = Shape::Square(Square { side: 4.0 });
    shape_circle.draw();
    shape_square.draw();
    
    println!("异构集合:");
    let shapes: Vec<Box<dyn Drawable>> = vec![
        Box::new(Circle { radius: 2.0 }),
        Box::new(Square { side: 4.0 }),
    ];
    render_scene(shapes);
    
    println!("使用枚举的异构集合:");
    let enum_shapes = vec![
        Shape::Circle(Circle { radius: 7.0 }),
        Shape::Square(Square { side: 5.0 }),
    ];
    render_scene_with_enum(enum_shapes);
    
    println!("建议：需要编译时确定类型用泛型，需要运行时处理多种类型用Trait对象");
    println!("使用枚举进行动态分发可以获得类型安全和更好的性能，但需要在编译时知道所有可能的类型");
    println!("枚举动态分发 vs Trait对象动态分发：");
    println!("  - 枚举：编译时知道所有类型，无虚函数调用开销，但扩展性差");
    println!("  - Trait对象：运行时确定类型，有虚函数调用开销，但扩展性好");
}

// 天坑四：给Trait"家族"添乱——不用关联类型，自找麻烦
fn demo_associated_types() {
    println!("4. 关联类型 vs 泛型参数：");
    
    // 不明智的做法 - 使用泛型参数
    trait StorageGeneric<T> {
        fn save(&self, item: T);
        fn load(&self) -> T;
    }
    
    // 更明智的做法 - 使用关联类型
    trait Storage {
        type Item;  // 关联类型
        fn save(&self, item: Self::Item);
        fn load(&self) -> Self::Item;
    }
    
    // 实现关联类型版本
    struct MemoryStorage;
    
    impl Storage for MemoryStorage {
        type Item = String;  // 指定具体类型
        
        fn save(&self, item: String) {
            println!("保存数据: {}", item);
        }
        
        fn load(&self) -> String {
            "从内存加载的数据".to_string()
        }
    }
    
    // 测试
    let storage = MemoryStorage;
    storage.save("重要数据".to_string());
    let loaded = storage.load();
    println!("加载数据: {}", loaded);
    
    println!("建议：当Trait中的类型与实现强相关时，使用关联类型");
}

// 天坑五：过早的"承诺"——在结构体上滥用约束
fn demo_struct_constraints() {
    println!("5. 结构体约束的正确使用方式：");
    
    // 不明智的做法 - 在结构体定义时添加约束
    /*
    struct WrapperBad<T: std::fmt::Display> {
        value: T,
    }
    */
    
    // 更明智的做法 - 结构体无约束，只在需要时添加
    struct Wrapper<T> {
        value: T,
    }
    
    // 只在需要打印的方法上添加Display约束
    impl<T: std::fmt::Display> Wrapper<T> {
        fn show(&self) {
            println!("包装的值: {}", self.value);
        }
    }
    
    // 可以创建任何类型的Wrapper，即使它不实现Display
    let _wrapper1 = Wrapper { value: 42 };  // 添加下划线前缀以避免警告
    let wrapper2 = Wrapper { value: "Hello" };

    // 只有在调用show方法时才需要T实现Display
    wrapper2.show(); // String实现了Display
    
    // 如果尝试对不实现Display的类型调用show会编译错误
    // wrapper1.show(); // i32实现了Display，所以这个可以调用
    
    println!("建议：给予结构体最大的自由，只在特定方法实现中提出要求");
}

// 结语：掌握了这些技巧，你的Rust代码将提升到一个全新的境界！
